from git import Repo
from pathlib import Path
from datetime import datetime
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
import seaborn as sns
import os
import numpy as np
import ast

# 确保visuals目录存在
os.makedirs('visuals', exist_ok=True)

# 设置matplotlib支持中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC", "sans-serif"]
plt.rcParams["axes.unicode_minus"] = False  # 确保负号正确显示


def generate_visualizations(repo_name, repo_commits, author_data, lines_changed, files_changed):
    """生成单个仓库的可视化图表并保存到visuals目录"""
    # 1. 前10位贡献者
    plot_top_contributors(author_data, repo_name)

    # 2. 过去12个月提交活动
    plot_monthly_activity(repo_commits, repo_name)

    # 3. 按星期提交活动分布
    plot_weekly_distribution(repo_commits, repo_name)

    # 4. 累计提交增长
    plot_cumulative_commits(repo_commits, repo_name)

    # 5. 每次提交的代码行变更分布
    plot_lines_changed(lines_changed, repo_name)

    # 6. 每次提交的文件变更分布
    plot_files_changed(files_changed, repo_name)


def plot_top_contributors(author_data, repo_name):
    """前10位贡献者条形图"""
    top_authors = author_data[:10]
    names = [author[0] for author in top_authors]
    commits = [author[1] for author in top_authors]

    plt.figure(figsize=(10, 6))
    sns.barplot(x=commits, y=names, hue=names, palette='viridis', legend=False)
    plt.title(f'Top 10 Contributors - {repo_name}')
    plt.xlabel('Number of Commits')
    plt.ylabel('Contributor Name')
    plt.tight_layout()

    # 规范命名：仓库名称-图表类型.png
    filename = f"visuals/{repo_name}-top_contributors.png"
    plt.savefig(filename, dpi=300, bbox_inches='tight')
    plt.close()


def plot_monthly_activity(repo_commits, repo_name):
    """过去12个月提交活动折线图"""
    # 获取最近12个月的提交数据
    end_date = datetime.now()
    start_date = end_date - pd.DateOffset(months=12)

    # 创建日期范围（更新频率代码为'ME'）
    date_range = pd.date_range(start=start_date, end=end_date, freq='ME')

    # 统计每月提交数
    monthly_data = []
    for commit in repo_commits:
        commit_date = datetime.fromtimestamp(commit.authored_date)
        if start_date <= commit_date <= end_date:
            monthly_data.append(commit_date.strftime('%Y-%m'))

    monthly_counts = pd.Series(monthly_data).value_counts().sort_index()

    # 确保所有月份都有数据
    full_range = [date.strftime('%Y-%m') for date in date_range]
    monthly_counts = monthly_counts.reindex(full_range, fill_value=0)

    # 格式化月份显示
    month_labels = [datetime.strptime(month, '%Y-%m').strftime('%b %Y') for month in monthly_counts.index]

    plt.figure(figsize=(12, 6))
    plt.plot(month_labels, monthly_counts.values, marker='o', linestyle='-')
    plt.title(f'Monthly Commit Activity - {repo_name} (Last 12 Months)')
    plt.xlabel('Month')
    plt.ylabel('Number of Commits')
    plt.xticks(rotation=45)
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.tight_layout()

    filename = f"visuals/{repo_name}-monthly_activity.png"
    plt.savefig(filename, dpi=300, bbox_inches='tight')
    plt.close()


def plot_weekly_distribution(repo_commits, repo_name):
    """按星期提交活动分布条形图"""
    weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
    day_counts = {day: 0 for day in weekdays}

    for commit in repo_commits:
        commit_date = datetime.fromtimestamp(commit.authored_date)
        day_counts[commit_date.strftime('%A')] += 1

    days = list(day_counts.keys())
    counts = list(day_counts.values())

    plt.figure(figsize=(10, 6))
    sns.barplot(x=days, y=counts, order=weekdays, color='steelblue')
    plt.title(f'Weekly Commit Distribution - {repo_name}')
    plt.xlabel('Day of Week')
    plt.ylabel('Number of Commits')
    plt.tight_layout()

    filename = f"visuals/{repo_name}-weekly_distribution.png"
    plt.savefig(filename, dpi=300, bbox_inches='tight')
    plt.close()


def plot_cumulative_commits(repo_commits, repo_name):
    """累计提交增长折线图"""
    # 按日期排序提交
    commit_dates = sorted([datetime.fromtimestamp(commit.authored_date) for commit in repo_commits])

    # 计算累计提交数
    cumulative_commits = range(1, len(commit_dates) + 1)

    plt.figure(figsize=(12, 6))
    plt.plot(commit_dates, cumulative_commits)
    plt.title(f'Cumulative Commits Over Time - {repo_name}')
    plt.xlabel('Date')
    plt.ylabel('Cumulative Number of Commits')

    # 设置日期格式
    plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
    plt.gca().xaxis.set_major_locator(mdates.YearLocator())
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.tight_layout()

    filename = f"visuals/{repo_name}-cumulative_commits.png"
    plt.savefig(filename, dpi=300, bbox_inches='tight')
    plt.close()


def plot_lines_changed(lines_changed, repo_name):
    """每次提交的代码行变更分布箱线图"""
    plt.figure(figsize=(10, 6))
    sns.boxplot(y=lines_changed, showfliers=False, color='skyblue')
    plt.title(f'Distribution of Lines Changed per Commit - {repo_name}')
    plt.ylabel('Total Lines Changed (Additions + Deletions)')
    plt.tight_layout()

    filename = f"visuals/{repo_name}-lines_changed.png"
    plt.savefig(filename, dpi=300, bbox_inches='tight')
    plt.close()


def plot_files_changed(files_changed, repo_name):
    """每次提交的文件变更分布箱线图"""
    plt.figure(figsize=(10, 6))
    sns.boxplot(y=files_changed, showfliers=False)
    plt.title(f'Distribution of Files Changed per Commit - {repo_name}')
    plt.ylabel('Number of Files Changed')
    plt.tight_layout()

    filename = f"visuals/{repo_name}-files_changed.png"
    plt.savefig(filename, dpi=300, bbox_inches='tight')
    plt.close()


def add_visualizations_to_report(report_path, repo_name):
    """将可视化图表添加到报告中（通过图片路径引用）"""
    with open(report_path, 'w', encoding='UTF-8') as f:
        f.write(f"# Visualizations for {repo_name}\n\n")

        # 添加前10位贡献者图表（更新图片引用路径）
        f.write("### Top 10 Contributors\n\n")
        f.write(f"![Top Contributors](visuals/{repo_name}-top_contributors.png)\n\n")

        # 添加月度活动图表
        f.write("### Monthly Commit Activity (Last 12 Months)\n\n")
        f.write(f"![Monthly Activity](visuals/{repo_name}-monthly_activity.png)\n\n")

        # 添加周分布图表
        f.write("### Weekly Commit Distribution\n\n")
        f.write(f"![Weekly Distribution](visuals/{repo_name}-weekly_distribution.png)\n\n")

        # 添加累计提交图表
        f.write("### Cumulative Commits Over Time\n\n")
        f.write(f"![Cumulative Commits](visuals/{repo_name}-cumulative_commits.png)\n\n")

        # 添加代码行变更图表
        f.write("### Lines Changed per Commit\n\n")
        f.write(f"![Lines Changed](visuals/{repo_name}-lines_changed.png)\n\n")

        # 添加文件变更图表
        f.write("### Files Changed per Commit\n\n")
        f.write(f"![Files Changed](visuals/{repo_name}-files_changed.png)\n\n")




def analyze_single_repo(repo_name, repo_url):
    """分析单个仓库并生成报告"""
    print(f"Analyzing repository: {repo_name}")

    # 克隆或加载仓库
    repo_path = Path(repo_name)
    if repo_path.exists() and (repo_path / ".git").exists():
        print(f"  Using existing repository at: {repo_path.resolve()}")
        repo = Repo(repo_path)
    else:
        print(f"  Cloning repository from: {repo_url}")
        repo = Repo.clone_from(repo_url, repo_name)

    # 收集提交数据
    print("  Collecting commit data...")
    repo_commits = list(repo.iter_commits())

    # 作者贡献统计
    author_data = {}
    for commit in repo_commits:
        author = commit.author.name
        author_data[author] = author_data.get(author, 0) + 1

    author_data = sorted(author_data.items(), key=lambda x: x[1], reverse=True)

    # 收集提交统计数据
    lines_changed = []
    files_changed = []
    commit_stats = []

    # 从缓存文件读取或重新收集提交统计数据
    cache_file = f"commit_stats_{repo_name}.txt"
    if Path(cache_file).exists():
        print("  Reading commit stats from cache")
        with open(cache_file, "r") as file:
            commit_stats = file.readlines()
    else:
        print("  Calculating commit stats and writing to cache")
        with open(cache_file, "w") as file:
            for commit in repo_commits:
                stats = str(commit.stats.total)
                commit_stats.append(stats)
                file.write(f"{stats}\n")

    # 解析统计数据
    for stats in commit_stats:
        try:
            stat = ast.literal_eval(stats)
            lines_changed.append(stat['lines'])
            files_changed.append(stat['files'])
        except (SyntaxError, ValueError, KeyError):
            continue

    generate_visualizations(repo_name, repo_commits, author_data, lines_changed, files_changed)

    # 创建只包含图片的报告
    report_path = f"report-{repo_name}.md"
    add_visualizations_to_report(report_path, repo_name)

    print(f"  Visual-only report saved to: {report_path}")
    return report_path


# 主程序
if __name__ == "__main__":
    # 要分析的仓库（替换为RuoYi-Vue）
    repo_name = "RuoYi-Vue"
    repo_url = "https://gitee.com/y_project/RuoYi-Vue"

    # 执行分析
    analyze_single_repo(repo_name, repo_url)

